import org.zjx.core.*;
import org.zjx.core.actions.*;
import org.zjx.core.builder.DecisionTreeBuilder;
import org.zjx.core.client.MemoryActionPuller;
import org.zjx.core.controller.DecisionTreeRegistry;
import org.zjx.core.controller.HotSwapDecisionTreeRegistry;
import org.zjx.core.engine.DecisionEngine;
import org.zjx.core.engine.InterruptManager;
import org.zjx.core.model.InterruptEvent;
import org.zjx.core.monitor.DecisionMonitor;
import org.zjx.core.nodes.*;
import org.zjx.core.state.ConcurrentStateAccessor;
import org.zjx.core.state.StateAccessor;
import org.zjx.core.state.StateComponent;
import org.zjx.core.state.StateValidator;
import org.zjx.util.DecisionUtils;

import java.util.*;
import java.util.concurrent.*;

public class DecisionSystemDemo {
    private static final int GAME_LOOP_INTERVAL_MS = 100;
    private static final String PLAYER_ID = "player1";

    // 状态类定义
    static class PlayerState implements StateComponent {
        private int hp = 100;
        private int energy = 50;
        private int attackPower = 10;

        @Override public void reset() { hp = 100; energy = 50; }
        @Override public StateComponent copy() {
            PlayerState copy = new PlayerState();
            copy.hp = this.hp;
            copy.energy = this.energy;
            return copy;
        }
        public int getHp() { return hp; }
        public void setHp(int hp) { this.hp = Math.max(0, Math.min(100, hp)); }
        public int getEnergy() { return energy; }
        public void setEnergy(int energy) { this.energy = Math.max(0, Math.min(100, energy)); }
        public int getAttackPower() { return attackPower; }
    }

    static class BattleState implements StateComponent {
        private int roundCount = 0;
        private boolean timeout = false;

        @Override public void reset() { roundCount = 0; timeout = false; }
        @Override public StateComponent copy() {
            BattleState copy = new BattleState();
            copy.roundCount = this.roundCount;
            copy.timeout = this.timeout;
            return copy;
        }
        public int getRoundCount() { return roundCount; }
        public void setRoundCount(int roundCount) { this.roundCount = roundCount; }
        public boolean isTimeout() { return timeout; }
        public void setTimeout(boolean timeout) { this.timeout = timeout; }
    }

    static class InventoryState implements StateComponent {
        private final Map<String, Integer> items = new HashMap<>();

        @Override public void reset() { items.clear(); }
        @Override public StateComponent copy() {
            InventoryState copy = new InventoryState();
            copy.items.putAll(this.items);
            return copy;
        }
        public void addItem(String itemId, int count) {
            items.merge(itemId, count, Integer::sum);
        }
        public boolean useItem(String itemId) {
            Integer count = items.get(itemId);
            if (count == null || count <= 0) return false;
            items.put(itemId, count - 1);
            return true;
        }
        public int getItemCount(String itemId) {
            return items.getOrDefault(itemId, 0);
        }
    }

    static class BossState implements StateComponent {
        private int hp = 100;

        @Override public void reset() { hp = 100; }
        @Override public StateComponent copy() {
            BossState copy = new BossState();
            copy.hp = this.hp;
            return copy;
        }
        public int getHp() { return hp; }
        public void setHp(int hp) { this.hp = Math.max(0, hp); }
    }

    public static void main(String[] args) {
        // 1. 初始化核心组件
        StateAccessor stateAccessor = new ConcurrentStateAccessor();
        StateValidator validator = createStateValidator();
        InterruptManager interruptManager = new InterruptManager();
        DecisionTreeRegistry registry = new HotSwapDecisionTreeRegistry();
        DecisionMonitor monitor = new DecisionMonitor(1.0, Set.of("ActionNode", "ConditionNode"), 1000);

        // 2. 初始化游戏状态
        initGameState(stateAccessor);

        // 3. 构建决策树
        DecisionTree mainDecisionTree = buildMainDecisionTree();
        registry.register("main", mainDecisionTree);

        // 4. 注册中断事件
        registerInterrupts(interruptManager);

        // 5. 创建决策引擎
        DecisionEngine engine = new DecisionEngine(
                interruptManager,
                new MemoryActionPuller(),
                registry.get("main").get(),
                validator,
                monitor
        );

        // 6. 启动游戏循环
        runGameLoop(engine, stateAccessor, monitor);
    }

    private static StateValidator createStateValidator() {
        StateValidator validator = new StateValidator();
        validator.addDomainRule(PlayerState.class, p -> p.getHp() >= 0 && p.getHp() <= 100);
        validator.addDomainRule(BattleState.class, b -> b.getRoundCount() >= 0);
        validator.addGlobalRule(accessor -> true);
        return validator;
    }

    private static void initGameState(StateAccessor accessor) {
        PlayerState player = new PlayerState();
        player.setHp(80);
        player.setEnergy(30);
        accessor.registerComponent(PlayerState.class, player);

        BattleState battle = new BattleState();
        battle.setRoundCount(1);
        accessor.registerComponent(BattleState.class, battle);

        InventoryState inventory = new InventoryState();
        inventory.addItem("health_potion", 5);  // 增加初始药水数量
        inventory.addItem("energy_potion", 3);
        accessor.registerComponent(InventoryState.class, inventory);
    }

    private static DecisionTree buildMainDecisionTree() {
        // 战斗决策子树
        DecisionNode battleTree = new DecisionTreeBuilder()
                .when((accessor, params) -> accessor.getComponent(BattleState.class)
                        .map(BattleState::isTimeout).orElse(false))
                .then(new ActionNode(new UltimateSkillAction(), null))
                .endCondition()
                .when((accessor, params) -> accessor.getComponent(PlayerState.class)
                        .map(p -> p.getEnergy() >= 100).orElse(false))
                .then(new ActionNode(new UltimateSkillAction(), null))
                .endCondition()
                .when((accessor, params) -> accessor.getComponent(BossState.class).isPresent())
                .then(new ActionNode(new BasicAttackAction(), null))
                .endCondition()
                .build();

        // 玩家决策子树
        DecisionNode playerTree = new DecisionTreeBuilder()
                .when((accessor, params) -> {
                    Optional<PlayerState> player = accessor.getComponent(PlayerState.class);
                    Optional<InventoryState> inventory = accessor.getComponent(InventoryState.class);
                    return player.isPresent() && inventory.isPresent()
                            && player.get().getHp() < 50  // 提高触发阈值
                            && inventory.get().getItemCount("health_potion") > 0;
                })
                .then(new ActionNode(
                        new SimpleGameAction("use_item", Map.of("item", "health_potion")),
                        null))
                .endCondition()
                .when((accessor, params) -> {
                    Optional<PlayerState> player = accessor.getComponent(PlayerState.class);
                    Optional<InventoryState> inventory = accessor.getComponent(InventoryState.class);
                    return player.isPresent() && inventory.isPresent()
                            && player.get().getEnergy() < 30  // 提高触发阈值
                            && inventory.get().getItemCount("energy_potion") > 0;
                })
                .then(new ActionNode(
                        new SimpleGameAction("use_item", Map.of("item", "energy_potion")),
                        null))
                .endCondition()
                .build();

        // 主决策树
        return new DefaultDecisionTree(
                new SequenceNode(
                        new SubTreeNode(battleTree, null, null),
                        new SubTreeNode(playerTree, null, null),
                        new ActionNode(new NextRoundAction(), null)
                ));
    }

    private static void registerInterrupts(InterruptManager manager) {
        manager.register(new InterruptEvent(
                InterruptEvent.Priority.HIGH,
                "boss_appear",
                () -> new ActionNode(new UltimateSkillAction(), null),
                (accessor, params) -> accessor.getComponent(BossState.class).isPresent(),
                5000
        ));

        manager.register(new InterruptEvent(
                InterruptEvent.Priority.CRITICAL,
                "low_hp_emergency",
                () -> new ActionNode(
                        new SimpleGameAction("use_item", Map.of("item", "health_potion")),
                        null),
                (accessor, params) -> {
                    Optional<PlayerState> player = accessor.getComponent(PlayerState.class);
                    Optional<InventoryState> inventory = accessor.getComponent(InventoryState.class);
                    return player.isPresent() && inventory.isPresent()
                            && player.get().getHp() < 20
                            && inventory.get().getItemCount("health_potion") > 0;
                },
                1000
        ));
    }

    private static void runGameLoop(DecisionEngine engine,
                                    StateAccessor stateAccessor,
                                    DecisionMonitor monitor) {
        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

        executor.scheduleAtFixedRate(() -> {
            try {
                // 1. 更新游戏状态
                updateGameState(stateAccessor);

                // 2. 执行决策
                Optional<GameAction> action = engine.nextAction(PLAYER_ID, stateAccessor);
                action.ifPresent(a -> executeAction(a, stateAccessor));

                // 3. 打印监控信息
                if (engine.getTotalRequests() % 10 == 0) {
                    printStats(engine, monitor,Optional.of(stateAccessor));
                }
            } catch (Exception e) {
                System.err.println("Error in game loop: " + e.getMessage());
            }
        }, 0, GAME_LOOP_INTERVAL_MS, TimeUnit.MILLISECONDS);
    }

    private static void updateGameState(StateAccessor accessor) {
        // 更新战斗状态
        accessor.getComponent(BattleState.class).ifPresent(battle -> {
            battle.setRoundCount(battle.getRoundCount() + 1);
            battle.setTimeout(battle.getRoundCount() % 3 == 0);

            // 每回合自动恢复1点HP
            accessor.getComponent(PlayerState.class).ifPresent(player -> {
                player.setHp(player.getHp() + 1);
            });
        });

        // 随机伤害 (40%概率)
        if (Math.random() < 0.4) {
            accessor.getComponent(PlayerState.class).ifPresent(player -> {
                int damage = 3 + (int)(Math.random() * 8);  // 3-10点伤害
                player.setHp(player.getHp() - damage);
                System.out.println("Player took " + damage + " damage! HP: " + player.getHp());
            });
        }

        // 随机Boss出现 (20%概率)
        if (Math.random() < 0.2 && !accessor.getComponent(BossState.class).isPresent()) {
            accessor.registerComponent(BossState.class, new BossState());
            System.out.println(">>>> BOSS APPEARED! <<<<");
        }
        // Boss自动消失 (当HP<=0或15%概率)
        else if (accessor.getComponent(BossState.class)
                .map(boss -> boss.getHp() <= 0 || Math.random() < 0.15)
                .orElse(false)) {
            accessor.registerComponent(BossState.class, null);
            System.out.println("<<<< BOSS DEFEATED >>>>");
        }
    }

    private static void executeAction(GameAction action, StateAccessor accessor) {
        System.out.println("Executing action: " + action.getActionId());

        switch (action.getActionId()) {
            case "basic_attack":
                accessor.getComponent(PlayerState.class).ifPresent(player -> {
                    int damage = player.getAttackPower();
                    accessor.getComponent(BossState.class).ifPresent(boss -> {
                        boss.setHp(boss.getHp() - damage);
                        System.out.printf("Dealt %d damage to boss! Boss HP: %d%n", damage, boss.getHp());
                        if (boss.getHp() <= 0) {
                            accessor.registerComponent(BossState.class, null);
                            System.out.println("<<<< BOSS DEFEATED! >>>>");
                        }
                    });
                    player.setEnergy(player.getEnergy() + 20);  // 增加能量获取
                    System.out.println("Energy gained: " + player.getEnergy());
                });
                break;

            case "ultimate_skill":
                accessor.getComponent(PlayerState.class).ifPresent(player -> {
                    player.setEnergy(0);
                    accessor.getComponent(BossState.class).ifPresent(boss -> {
                        boss.setHp(boss.getHp() - 50);
                        System.out.printf("ULTIMATE HIT! Boss HP: %d%n", boss.getHp());
                        if (boss.getHp() <= 0) {
                            accessor.registerComponent(BossState.class, null);
                            System.out.println("<<<< BOSS DEFEATED! >>>>");
                        }
                    });
                });
                break;

            case "use_item":
                String item = (String) action.getParams().get("item");
                accessor.getComponent(InventoryState.class).ifPresent(inventory -> {
                    if (inventory.useItem(item)) {
                        System.out.println("Used " + item);
                        accessor.getComponent(PlayerState.class).ifPresent(player -> {
                            if ("health_potion".equals(item)) {
                                player.setHp(player.getHp() + 40);  // 增加治疗效果
                                System.out.println("HP restored to: " + player.getHp());
                            } else if ("energy_potion".equals(item)) {
                                player.setEnergy(player.getEnergy() + 60);  // 增加能量恢复
                                System.out.println("Energy restored to: " + player.getEnergy());
                            }
                        });
                    } else {
                        System.out.println(item + " not available!");
                    }
                });
                break;

            case "next_round":
                System.out.println("--- Next Round [" +
                        accessor.getComponent(BattleState.class).map(b -> b.getRoundCount()).orElse(0) +
                        "] ---");
                break;

            default:
                System.out.println("Unknown action: " + action.getActionId());
        }
    }

    private static void printStats(DecisionEngine engine, DecisionMonitor monitor,Optional<StateAccessor> stateAccessor) {
        System.out.println("\n=== System Stats ===");
        System.out.println("Total requests: " + engine.getTotalRequests());
        System.out.println("Success count: " + engine.getSuccessCount());
        System.out.println("Timeout count: " + engine.getTimeoutCount());
        System.out.println("Interrupt count: " + engine.getInterruptCount());

        System.out.println("\nNode execution stats:");
        monitor.getNodeStats().forEach((nodeId, stats) -> {
            System.out.printf("%s: count=%d, avgTime=%.2fms, errors=%d%n",
                    nodeId, stats.getExecutionCount(),
                    stats.getAvgTimeNanos() / 1_000_000.0,
                    stats.getErrorCount());
        });

        // 打印当前状态
        System.out.println("\nCurrent State:");
        stateAccessor.ifPresent(accessor -> {
            accessor.getComponent(PlayerState.class).ifPresent(player -> {
                System.out.println("Player HP: " + player.getHp() + " Energy: " + player.getEnergy());
            });
            accessor.getComponent(InventoryState.class).ifPresent(inv -> {
                System.out.println("Inventory: Health Potions=" + inv.getItemCount("health_potion") +
                        " Energy Potions=" + inv.getItemCount("energy_potion"));
            });
            accessor.getComponent(BossState.class).ifPresent(boss -> {
                System.out.println("Boss HP: " + boss.getHp());
            });
        });
    }

    // 简单游戏动作实现
    static class SimpleGameAction implements GameAction {
        private final String actionId;
        private final Map<String, Object> params;

        public SimpleGameAction(String actionId, Map<String, Object> params) {
            this.actionId = actionId;
            this.params = new HashMap<>(params);
        }
        @Override
        public void execute() {

        }
        @Override public String getActionId() { return actionId; }
        @Override public Map<String, Object> getParams() { return params; }
        @Override public void validate() {}
    }
}